/*
 * Copyright 2007 MBARI
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package org.mbari.vcr;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.mbari.util.NumberUtil;
import org.mbari.vcr.rs422.VCR;
import org.mbari.vcr.rs422.VCRReply;

/**
 * Class description
 *
 *
 * @version    $Id: $
 * @author     Brian Schlining    
 */
public class VCRTestRxtx1 {

    InputStream in;
    OutputStream out;
    SerialPort serialPort;
    private long receiveTimeout = 40;

    /**
     * Constructs ...
     *
     *
     * @param serialPortName
     *
     * @throws IOException
     * @throws NoSuchPortException
     * @throws PortInUseException
     * @throws UnsupportedCommOperationException
     */
    public VCRTestRxtx1(String serialPortName)
            throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException, IOException {
        init(serialPortName);
    }

    /**
     * Constructs ...
     *
     *
     * @param serialPortName
     * @param receiveTimeout
     *
     * @throws IOException
     * @throws NoSuchPortException
     * @throws PortInUseException
     * @throws UnsupportedCommOperationException
     */
    public VCRTestRxtx1(String serialPortName, long receiveTimeout)
            throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException, IOException {
        this.receiveTimeout = receiveTimeout;
        init(serialPortName);
    }

    void init(String serialPortName)
            throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException, IOException {
        CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(serialPortName);
        serialPort = (SerialPort) portId.open("VCR", 2000);
        in = serialPort.getInputStream();
        out = serialPort.getOutputStream();
        serialPort.setSerialPortParams(38400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_ODD);
        serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN & SerialPort.FLOWCONTROL_RTSCTS_OUT);

        ((CommPort) serialPort).enableReceiveTimeout((int) receiveTimeout);    // Returns after waiting 190ms

    }

    /**
     * Method description
     *
     *
     * @return
     *
     * @throws IOException
     * @throws InterruptedException
     */
    public byte[] receive() throws IOException, InterruptedException {

        // Get the command returned by the VCR
        final byte[] cmd = new byte[2];
        in.read(cmd);
        Thread.sleep(33);

        // Extract the number of data bytes in the command block. Then
        // read the data from the serial port
        final int numDataBytes = (int) (cmd[0] & 0x0F);    // Get the number of data blocks
        byte[] data = null;
        if (numDataBytes > 0) {
            data = new byte[numDataBytes];
            in.read(data);
        }

        Thread.sleep(33);

        // Read the checksum that the VCR sends
        final byte[] checksum = new byte[1];
        in.read(checksum);

        /*
         * Munge it all into a single byte array
         */
        int dataLength = (data == null) ? 0 : data.length;
        final byte[] c = new byte[cmd.length + dataLength + 1];
        System.arraycopy(cmd, 0, c, 0, cmd.length);

        if (data != null) {
            System.arraycopy(data, 0, c, cmd.length, data.length);
        }

        c[c.length - 1] = checksum[0];

        System.out.println("<< " + NumberUtil.toHexString(c));

        return c;
    }

    /**
     * Method description
     *
     *
     * @param data
     *
     * @throws IOException
     * @throws InterruptedException
     */
    public void send(byte[] data) throws IOException, InterruptedException {
        Thread.sleep(33);
        byte checksum = VCRReply.calculateChecksum(data);
        final byte[] c = new byte[data.length + 1];
        System.arraycopy(data, 0, c, 0, data.length);
        c[c.length - 1] = checksum;
        System.out.println(">> " + NumberUtil.toHexString(c));
        out.write(c);
    }

    /**
     * Method description
     *
     *
     * @param args
     */
    public static void main(String[] args) {
        int ok = 0;
        try {
            byte[] response = null;
            VCRTestRxtx1 test = new VCRTestRxtx1("COM2");
            test.send(VCR.GET_STATUS);
            response = test.receive();
            test.send(VCR.GET_TIMECODE);
            response = test.receive();
            test.send(VCR.PLAY_FWD);
            response = test.receive();
            test.send(VCR.GET_STATUS);
            response = test.receive();
            test.send(VCR.GET_TIMECODE);
            response = test.receive();
            Thread.sleep(2000);
            test.send(VCR.STOP);
            response = test.receive();
            test.send(VCR.GET_TIMECODE);
            response = test.receive();
            Thread.sleep(2000);
            test.send(VCR.GET_TIMECODE);
            response = test.receive();
            Thread.sleep(2000);
            test.send(VCR.GET_TIMECODE1);
            response = test.receive();
            Thread.sleep(2000);
            test.send(VCR.GET_TIMECODE2);
            response = test.receive();
            Thread.sleep(2000);
            test.send(VCR.GET_STATUS);
            response = test.receive();
            Thread.sleep(2000);
        }
        catch (Exception e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
            ok = -1;
        }

        System.exit(ok);
    }
}
